home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Communications / pcomm / Source / expand.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-06-12  |  2.8 KB  |  149 lines

  1. /*
  2.  * Do file name expansion with "native" shell.  Using the native shell
  3.  * (as described in the SHELL environmental variable) allows for csh or
  4.  * ksh abbreviations that sh doesn't recognize.  Returns a pointer to
  5.  * a static area.
  6.  */
  7.  
  8. #define EXPAND_BUF    2048
  9.  
  10. #include <stdio.h>
  11. #include <signal.h>
  12. #include <fcntl.h>
  13. #include "config.h"
  14.  
  15. char *
  16. expand(input)
  17. char *input;
  18. {
  19.     extern char *null_ptr;
  20.     FILE *pfp, *n_popen();
  21.     int last;
  22.     char buf[1024], *strpbrk(), *strcpy();
  23.     static char ans[EXPAND_BUF];
  24.  
  25.                     /* same rules as str_dup() */
  26.     if (input == NULL)
  27.         return(NULL);
  28.     if (*input == '\0')
  29.         return(null_ptr);
  30.                     /* any thing to expand? */
  31.     if (!strpbrk(input, "$*{}[]\\?~")) {
  32.         strcpy(ans, input);
  33.         return(ans);
  34.     }
  35.                     /* popen an echo */
  36.     sprintf(buf, "echo %s", input);
  37.  
  38.     pfp = n_popen(buf, "r");
  39.     fgets(ans, EXPAND_BUF, pfp);
  40.     n_pclose(pfp);
  41.  
  42.     if (!strlen(ans)) {
  43.         strcpy(ans, input);
  44.         return(ans);
  45.     }
  46.     /*
  47.      * A horrible kludge...  if the last character is not a line
  48.      * feed, then the csh has returned an error message.  Otherwise
  49.      * zap the line feed.
  50.      */
  51.     last = strlen(ans) -1;
  52.     if (ans[last] != '\n') {
  53.         strcpy(ans, input);
  54.         return(ans);
  55.     }
  56.     else
  57.         ans[last] = '\0';
  58.  
  59.     return(ans);
  60. }
  61.  
  62. #define    tst(a,b) (*mode == 'r'? (b) : (a))
  63. #define    RDR    0
  64. #define    WTR    1
  65. static int popen_pid[20];
  66.  
  67. FILE *
  68. n_popen(cmd, mode)
  69. char *cmd, *mode;
  70. {
  71.     int myside, hisside, ppid, p[2];
  72.     char *shellpath, *shell, *flags, *getenv(), *strrchr();
  73.     void _exit();
  74.  
  75.     if (pipe(p) < 0)
  76.         return NULL;
  77.  
  78.     myside = tst(p[WTR], p[RDR]);
  79.     hisside = tst(p[RDR], p[WTR]);
  80.                     /* get the environmental variable */
  81.     shellpath = getenv("SHELL");
  82.     if (shellpath == NULL || *shellpath == '\0')
  83.         shellpath = "/bin/sh";
  84.  
  85.     if (shell = strrchr(shellpath, '/'))
  86.         shell++;
  87.     else {
  88.         shellpath = "/bin/sh";
  89.         shell = "sh";
  90.     }
  91.                     /* fix up the flags */
  92.     if (!strcmp(shell, "csh"))
  93.         flags = "-fc";
  94.     else
  95.         flags = "-c";        /* Korn shell too */
  96.  
  97.     if (!(ppid = fork())) {
  98.         int stdio;
  99.                     /* no error messages please */
  100.         close(2);
  101.         open("/dev/null", O_WRONLY);
  102. #ifdef SETUGID
  103.         setgid(getgid());
  104.         setuid(getuid());
  105. #endif /* SETUGID */
  106.         stdio = tst(0, 1);
  107.         close(myside);
  108.         close(stdio);
  109.         fcntl(hisside, F_DUPFD, stdio);
  110.         close(hisside);
  111.         execl(shellpath, shell, flags, cmd, (char *) 0);
  112.         _exit(1);
  113.     }
  114.     if (ppid == -1) {
  115.         close(myside);
  116.         close(hisside);
  117.         return NULL;
  118.     }
  119.  
  120.     popen_pid[myside] = ppid;
  121.  
  122.     close(hisside);
  123.     return(fdopen(myside, mode));
  124. }
  125.  
  126. n_pclose(ptr)
  127. FILE *ptr;
  128. {
  129.     SIG_TYPE (*hstat)(), (*istat)(), (*qstat)();
  130.     int f, r, sig_status;
  131.  
  132.     f = fileno(ptr);
  133.     fclose(ptr);
  134.     istat = signal(SIGINT, SIG_IGN);
  135.     qstat = signal(SIGQUIT, SIG_IGN);
  136.     hstat = signal(SIGHUP, SIG_IGN);
  137.  
  138.     while ((r = wait(&sig_status)) != popen_pid[f] && r != -1)
  139.         ;
  140.  
  141.     if (r == -1)
  142.         sig_status = -1;
  143.  
  144.     signal(SIGINT, istat);
  145.     signal(SIGQUIT, qstat);
  146.     signal(SIGHUP, hstat);
  147.     return(sig_status);
  148. }
  149.